do	--[[ RENDER MODULE ]]--
	
	local	_SUPER_RENDER_OBJ, _ENT_RENDER_OBJ, _RENDER_PASS, _ENT_RENDER_PASS = {},{},{},{}
	
	
	--[[ _RENDER_PASS <-> render::pass ]]--
	
	
	local	SA_PROP_noop = function() return end
	local	SA_PROP_bnoop = function() return true end
	
	_RENDER_PASS.__metatable = {}
	
	-- GEO.render[k][y], where render[k] exists and this == nil
	_RENDER_PASS.__index = function( s, k )
		-- = array_get( GEO.render[i], k )
		
		-- bool GEO.render[k].active = true
		-- pass will be skipped if inactive
		
		-- (virtual) bool GEO.render[k]:Pre() = no_op
		-- pre-pass call - if return value is false pass will be skipped
		
		-- (virtual) bool GEO.render[k]:entPre( ent ) = no_op
		-- pre-pass call - if return value is false pass skips over this ent
		
		-- (virtual) void GEO.render[k]:entPost( ent ) = no_op
		-- post-pass call - per-ent cleanup. called along FILO order
		
		-- (virtual) void GEO.render[k]:Post() = no_op
		-- post-pass call - per-pass cleanup. called along FILO order
		
		if
			k == 'active'
		then
			rawset(s, k, true)
			return	rawget(s, k)
		elseif
			k == 'entPre'
		then
			rawset(s, k, SA_PROP_bnoop)
			return	rawget(s, k)
		elseif
			k == 'entPost'
		then
			rawset(s, k, SA_PROP_noop)
			return	rawget(s, k)
		elseif
			k == 'Pre'
		then
			rawset(s, k, SA_PROP_bnoop)
			return	rawget(s, k)
		elseif
			k == 'Post'
		then
			rawset(s, k, SA_PROP_noop)
			return	rawget(s, k)
		end
		return	nil
	end
	
	-- bool (GEO.render[x])()
	-- executes a render pass with some options
	-- returns false if the pass did not happen for some reason
	_RENDER_PASS.__call = function( sa )
		-- check if pass is active
		-- check / set render options
		-- execute pass
		-- restore render options
		
		if		not sa.active
		then	return	false
		
		elseif	not sa:Pre()
		then	return	false
		end
		
		GEO.render.ExecutePass( sa )
		
		sa:Post()
		
		return	true
	end
	
	
	--[[ RENDER SP OBJECT ]]--
	
	local	function _SUPER_RENDER_OBJ_PROP_new( parent, base )
		return	GEO.core.moveto( GEO.core.Obj('render','SA',base), parent )
	end
	
	-- void GEO.render.ExecutePass( pass )
	local	SP_PROP_ExecutePass = function( pass )
		-- for each Ent
		-- call Ent:render( pass )
		
		for	k, ent
		in	ipairs( GEO )
		do	ent:render( pass )
		end
		
	end
	
	SP.__metatable = {}
	
	-- GEO.render[k], where this == nil
	SP.__index = function( s, k )
		
		-- GEO.render:new{...} method
		-- creates an SA object and parents it to GEO.render (see above)
		
		-- void GEO.render.ExecutePass( pass )
		-- begins a global render pass.
		
		-- bool GEO.render.active = true
		-- render is active by default.
		
		if		k == 'new'
		then	return	_RENDER_PASS_PROP_new
		
		elseif	k == 'ExecutePass'
		then	return	SP_PROP_ExecutePass
		
		elseif	k == 'active'
		then	rawset(s, k, true)
				return	s[k]
		end
		
		return	nil
		
	end -- GEO.render[k]
	
	-- int GEO.render()
	SP.__call = function( s )
		-- if not active skip this step
		-- loop through all super actions
		-- call the render super action (render pass)
		-- return number of passes
		
		if		not s.active
		then	return 0
		end
		
		local	passes = 0
		
		for	k, v
		in	ipairs( s )
		do	passes = passes + ( v() and 1 or 0 )
		end
		
		return	passes
		
	end -- bool GEO.render()
	
	
	local function newEA( parent, base )
		return	GEO.core.moveto( GEO.core.Obj('render','EA',base), parent )
	end
	
	
	--[[ RENDER EP OBJECT ]]--
	
	-- void Ent.render.display_func( Ent )
	-- renders raw geometry for Ent
	local	EP_PROP_display_func_default = function( e )
		-- todo: render logic here
		return
	end
	
	EP.__metatable = {}
	
	-- Ent.render[k], where this == nil
	EP.__index = function( s, k )
		-- bool Ent.render.visible = true
		-- (virtual) void Ent.render.display_func( Ent )
		
		if		k == 'visible'
		then	rawset(s, k, true);
				return	true
		
		elseif	k == 'display_func'
		then	rawset(s, k, EP_PROP_display_func_default);
				return	rawget(s, k)
		end
		
		return	nil
		
	end -- Ent.render[k]
	
	-- void Ent:render( [pass] )
	EP.__call = function( s, ent, pass )
		-- if object invisible, skip
		-- if pass object ommitted / invalid, just render the geometry
		-- otherwise check pass entPre
		-- then render geom
		-- then pass entPost
		
		if		not s.visible
		then	return
		
		elseif	not pass
		then	s.display_func( s )
		
		elseif	pass.gstype and pass.gstype == 'render::SA'
		then
				if		not pass:entPre( ent )
				then	return
				end
				
				s.display_func( ent )
				
				pass:entPost( ent )
		end
	end -- void Ent:render( pass )
	
	
	
	-- insert 'render' module into GEO.mod, activating it.
	GEO.core.mod.render = {render=SP, SA=SA, Ent=EP} -- , Ent=EP, EA=EA}
	
end -- render module
